package com.share.pss.tool;

import java.util.Arrays;

/**工具类 生成随机验证码字符串
 * @author MrZhang 
 * @date 2018年3月8日 下午7:28:14
 * @version V1.0 
 */
public class SecurityCode {
	/*验证码难度级别,Simple只包含数字，Medium包含数字和小写英文，Hard包含数字和大小写英文*/
	public enum SecurityCodeLevel{Simple,Medium,Hard};
	/**产生默认验证码，4位中等难度
	 * @return String 验证码
	 * 2018年3月10日下午2:17:06
	 */
	public static String getSecurityCode(){
		return getSecurityCode(4,SecurityCodeLevel.Medium,false);
	}
	/**产生长度和难度任意的验证码
	 * @param length 长度
	 * @param level 难度
	 * @param isCanRepeat 是否能够出现重复字符，如果true，则可出现5578类似的，false，则不出现。
	 * @return String 验证码
	 * 2018年3月10日下午2:14:34
	 */
	public static String getSecurityCode(int length,SecurityCodeLevel level,boolean isCanRepeat){
		//随机抽取len个长度字符
		int len = length;
		//字符集合（出去易混淆的数字0，1，字母l，o，O）
		char[] codes={'1','2','3','4','5','6','7','8','9',
                      'a','b','c','d','e','f','g','h','i',
                      'j','k','m','n','p','q','r','s','t',
                      'u','v','w','x','y','z','A','B','C',
                      'D','E','F','G','H','I','J','K','L',
                      'M','N','P','Q','R','S','T','U','V',
                      'W','X','Y','Z'}; 
		//根据不同的难度截取字符数组
		if(level==SecurityCodeLevel.Simple){
			codes=Arrays.copyOfRange(codes, 0, 9);
		}else if(level==SecurityCodeLevel.Medium){
			codes=Arrays.copyOfRange(codes, 0, 33);
		}
		//字符集合长度
		int n = codes.length;
		//抛出运行时异常
		if(len>n&& isCanRepeat==false){
			throw new RuntimeException(String.format("调用SecurityCode.getSecurityCode(%1$s,%2$s,%3$s)出现异常，"+
													 "当isCanRepeat为%3$s时，传入参数%1$s不能大于%4$s", len,level,isCanRepeat,n));
		}
		//创建数组存放抽取出来的字符
		char[] result = new char[len];
		//判断能否出现重复的字符
		if(isCanRepeat){
			for (int i = 0; i < result.length; i++) {
				//索引0 and n-1
				int r = (int) (Math.random()*n);
				//将result中的第i个元素设置为codes[r]存放的数值
				result[i]=codes[r];
			}
		}else{
			for (int i = 0; i < result.length; i++) {
				// 索引 0 and n-1
				int r = (int) (Math.random() * n);
				// 将result中的第i个元素设置为codes[r]存放的数值
				result[i] = codes[r];
				// 必须确保不会再次抽取到那个字符，因为所有抽取的字符必须不相同。
				// 因此，这里用数组中的最后一个字符改写codes[r]，并将n减1
				codes[r] = codes[n - 1];
				n--;
			}
		}
		return String.valueOf(result);
	}
}
